package com.ymdx.dao.impl;

import com.ymdx.dao.BaseDao;
import com.ymdx.entity.IdEntity;
import com.ymdx.util.Page;
import com.ymdx.util.tool.ReflectUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;

//import org.hibernate.query.*;
//import org.hibernate.query.Query;


/**
 * @param <T>
 * @param <PK>
 * @author hcq
 */
public class BaseDaoImpl<T extends IdEntity, PK extends Serializable> implements BaseDao<T, PK> {

    // ~ Instance fields =======================================================
    protected final Logger log = LoggerFactory.getLogger(getClass());

    protected SessionFactory sessionFactory;
    protected Class<T> entityClass;

    // ~ Constructor ===========================================================
    public BaseDaoImpl() {
        this.entityClass = ReflectUtils.getSuperClassType(getClass());
    }

    public BaseDaoImpl(SessionFactory sessionFactory) {
        this.entityClass = ReflectUtils.getSuperClassType(getClass());
        this.sessionFactory = sessionFactory;
    }

    public BaseDaoImpl(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public BaseDaoImpl(SessionFactory sessionFactory, Class<T> entityClass) {
        this.sessionFactory = sessionFactory;
        this.entityClass = entityClass;
    }

    // ~ Methods ===============================================================

    /**
     * @return the sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * @param sessionFactory the sessionFactory to set
     */
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * @return the entityClass
     */
    public Class<T> getEntityClass() {
        return entityClass;
    }

    /**
     * @param entityClass the entityClass to set
     */
    public void setEntityClass(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public Session getSession() {
        return getCurrentSession();
    }

    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    public Session openSession() {
        return sessionFactory.openSession();
    }


    @Override
    public Page<T> page(String hql, Page<T> page, Object... objs) {
        if (page.isAutoCount()) {
            String preHql = "select count(*) ";
            Query countQuery = getSession().createQuery(preHql + hql);
            for (int i = 0; i < objs.length; i++) {
                countQuery.setParameter(i, objs[i]);
            }
            Long totalCount = (Long) countQuery.uniqueResult();
            if (totalCount == null || totalCount == 0) {
                page.setTotalCount(0);
                return page;
            }
            page.setTotalCount(totalCount);
        }
        String suffHql = " order by modifyTime desc ";
        Query query = getSession().createQuery(hql+suffHql);
        for (int i = 0; i < objs.length; i++) {
            query.setParameter(i, objs[i]);
        }
        query.setFirstResult((page.getPageNo() - 1)*page.getPageSize());
        query.setMaxResults(page.getPageSize());
        page.setResult(query.list());
        return page;
    }


}
